package org.example.dao;

import org.example.biz.HelloBiz;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CGLIBProx {

    public static <T> T proxy(T readSubject){
        Enhancer enhancer = new Enhancer();
        // 设置父类
        enhancer.setSuperclass(readSubject.getClass());
        // 设置回调对象(方法拦截器)
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object proxy,
                                    Method method,
                                    Object[] args,
                                    MethodProxy methodProxy) throws Throwable {
                System.out.println("前置拦截");
                Object ret = methodProxy.invoke(readSubject, args);
                System.out.println("后置拦截");
                return ret;
            }
        });
        return (T) enhancer.create();
    }

    public static void main(String[] args) {
        HardDisk hardDisk = new HardDisk();
        UsbDisk usbDisk = new UsbDisk();
        Storage proxyHardDisk = proxy(hardDisk);
        Storage proxyUsbDisk = proxy(usbDisk);
        // 通过代理执行业务方法
        System.out.println("---------------------------");
        proxyHardDisk.save("书籍");
        System.out.println("---------------------------");
        proxyUsbDisk.save("书籍");
        System.out.println("---------------------------");
        // 被代理对象必须实现接口
        HelloBiz helloBiz = proxy(new HelloBiz("张三"));
        helloBiz.hello();

        // CGLIB 动态字节码技术, 程序运行时创建和加载类
        // CGLIB实现动态代理, 在运行时创建被代理对象的子类
        // CGLIB代理对象是被代理对象的子类
        // JDK代理对象时被代理对象的兄弟类
    }
}
